package vn.orderonline.core.redis;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisException;
import vn.orderonline.core.commons.utils.JsonUtils;
import vn.orderonline.core.redis.model.RedisFactory;

public class RedisService {
	private static final Logger LOGGER = LoggerFactory.getLogger(RedisService.class);
	
	@Autowired
	private RedisFactory redisFactory;
	
	private static final int EXPIRE = 3600;
	
	public RedisService() {
		
	}
	
	public void set(String key, Object value) {
		Jedis writer = null;
		String strValue;
		try {
			writer = redisFactory.getWriter();
			strValue = JsonUtils.toJson(value);
			writer.set(key, strValue);
			writer.expire(key, EXPIRE);
		} catch (JedisException e) {
			if (writer != null) {
				redisFactory.returnBrokenWriteResource(writer);
				writer = null;
			}
			LOGGER.error(e.getMessage(), e);
		} finally {
			if (writer != null) {
				redisFactory.returnWriteResource(writer);
				writer = null;
			}
		}
	}
	
	public void hset(String key, String field, Object value) {
		Jedis writer = null;
		String strValue;
		try {
			writer = redisFactory.getWriter();
			strValue = JsonUtils.toJson(value);
			writer.hset(key, field, strValue);
			writer.expire(key, EXPIRE);
		} catch (JedisException e) {
			if (writer != null) {
				redisFactory.returnBrokenWriteResource(writer);
				writer = null;
			}
			LOGGER.error(e.getMessage(), e);
		} finally {
			if (writer != null) {
				redisFactory.returnWriteResource(writer);
				writer = null;
			}
		}
	}
	
	public void hset(String key, Map<String, String> hashmap) {
		Jedis writer = null;
		try {
			writer = redisFactory.getWriter();
			writer.hmset(key, hashmap);
			writer.expire(key, EXPIRE);
		} catch (JedisException e) {
			if (writer != null) {
				redisFactory.returnBrokenWriteResource(writer);
				writer = null;
			}
			LOGGER.error(e.getMessage(), e);
		} finally {
			if (writer != null) {
				redisFactory.returnWriteResource(writer);
				writer = null;
			}
		}
	}
	
	public <T> void hmset(String key, Map<String, T> values) {
		Jedis writer = null;
		String strValue;
		if (values != null && !values.isEmpty()) {
			writer = redisFactory.getWriter();
			try {
				for (Map.Entry<String, T> entry : values.entrySet()) {
					strValue = JsonUtils.toJson(entry.getValue());
					writer.hset(key, entry.getKey(), strValue);
					writer.expire(key, EXPIRE);
				}
			} catch (JedisException e) {
				if (writer != null) {
					redisFactory.returnBrokenWriteResource(writer);
					writer = null;
				}
			} finally {
				if (writer != null) {
					redisFactory.returnWriteResource(writer);
					writer = null;
				}
			}
		}
	}
	
	public void delete(String key) {
		Jedis writer = null;
		try {
			writer = redisFactory.getWriter();
			writer.del(key);
		} catch (JedisException e) {
			if (writer != null) {
				redisFactory.returnBrokenWriteResource(writer);
				writer = null;
			}
			LOGGER.error(e.getMessage(), e);
		} finally {
			if (writer != null) {
				redisFactory.returnWriteResource(writer);
				writer = null;
			}
		}
	}
	
	public void delete(String... keys) {
		Jedis writer = null;
		try {
			writer = redisFactory.getWriter();
			for (String key : keys) {
				writer.del(key);
			}
		} catch (JedisException e) {
			if (writer != null) {
				redisFactory.returnBrokenWriteResource(writer);
				writer = null;
			}
			LOGGER.error(e.getMessage(), e);
		} finally {
			if (writer != null) {
				redisFactory.returnWriteResource(writer);
				writer = null;
			}
		}
	}
	
	public void hdelete(String key, String field) {
		Jedis writer = null;
		try {
			writer = redisFactory.getWriter();
			writer.hdel(key, field);
		} catch (JedisException e) {
			if (writer != null) {
				redisFactory.returnBrokenWriteResource(writer);
				writer = null;
			}
			LOGGER.error(e.getMessage(), e);
		} finally {
			if (writer != null) {
				redisFactory.returnWriteResource(writer);
				writer = null;
			}
		}
	}
	
	public <T> T get(String key, Class<T> clazz) {
		Jedis reader = null;
		T objectResult = null;
		try {
			reader = redisFactory.getReader();
			String result = reader.get(key);
			if (result != null) {
				objectResult = JsonUtils.fromJson(result, clazz);
			}
		} catch (JedisException e) {
			if (reader != null) {
				redisFactory.returnBrokenReadResource(reader);
				reader = null;
			}
			LOGGER.error(e.getMessage(), e);
		} finally {
			if (reader != null) {
				redisFactory.returnReadResource(reader);
				reader = null;
			}
		}
		return objectResult;
	}
	
	public <T> T hget(String key, Class<T> clazz, String keys) {
		Jedis reader = null;
		T objectResult = null;
		try {
			reader = redisFactory.getReader();
			String result = reader.hget(key, keys);
			if (result != null) {
				objectResult = JsonUtils.fromJson(result, clazz);
			}
		} catch (JedisException e) {
			if (reader != null) {
				redisFactory.returnBrokenReadResource(reader);
				reader = null;
			}
			LOGGER.error(e.getMessage(), e);
		} finally {
			if (reader != null) {
				redisFactory.returnReadResource(reader);
				reader = null;
			}
		}
		return objectResult;
	}
	
	public <T> List<T> mget(Set<String> keys, Class<T> clazz) {
		List<T> objects = Collections.emptyList();
		Jedis reader = null;
		try {
			reader = redisFactory.getReader();
			List<String> values = reader.mget(keys.toArray(new String[keys.size()]));
			
			objects = new ArrayList<>(values.size());
			for (String value: values) {
				if (value != null) {
					objects.add(JsonUtils.fromJson(value, clazz));
				}
			}
		} catch (JedisException e) {
			if (reader != null) {
				redisFactory.returnBrokenReadResource(reader);
				reader = null;
			}
			LOGGER.error(e.getMessage(), e);
		} finally {
			if (reader != null) {
				redisFactory.returnReadResource(reader);
				reader = null;
			}
		}
		
		
		return null;
	}
	
	public Boolean contains(String key) {
		Jedis reader = null;
		Boolean isContain = false;
		try {
			reader = redisFactory.getReader();
			isContain = reader.exists(key);
		} catch (JedisException e) {
			if (reader != null) {
				redisFactory.returnBrokenReadResource(reader);
				reader = null;
			}
			LOGGER.error(e.getMessage(), e);
		} finally {
			if (reader != null) {
				redisFactory.returnReadResource(reader);
				reader = null;
			}
		}
		return isContain;
	}

}
